home *** CD-ROM | disk | FTP | other *** search
- // Copyright (C) 1996, 1997 Meta Four Software. All rights reserved.
- //
- // Views and other core class declarations
- //
- //! rev="$Id: k4view.h,v 1.21 1997/06/05 08:31:53 jcw Rel $"
-
- #ifndef __K4VIEW_H__
- #define __K4VIEW_H__
-
- #ifndef __K4CONF_H__
- #error Please include "k4conf.h" before this header file
- #endif
-
- /////////////////////////////////////////////////////////////////////////////
- // Declarations in this file
-
- class c4_View; // a view on underlying data
- class c4_Cursor; // an index into a view
- class c4_RowRef; // a reference to a row
- class c4_Row; // one row in a view
- class c4_Storage; // manages view persistence
- class c4_Bytes; // used to pass around generic data
-
- class c4_Property; // for access inside rows
- class c4_IntProp;
- class c4_FloatProp;
- class c4_DoubleProp;
- class c4_StringProp;
- class c4_BytesProp;
- class c4_ViewProp;
-
- // defined in "k4viewx.h", included at the end of this file
- class c4_Sequence;
-
- class c4_Reference;
- class c4_IntRef;
- class c4_FloatRef;
- class c4_DoubleRef;
- class c4_StringRef;
- class c4_BytesRef;
- class c4_ViewRef;
-
- class c4_Persist; // not defined here
- class c4_Strategy; // not defined here
- class c4_Table; // not defined here
-
- /////////////////////////////////////////////////////////////////////////////
- //: A collection of data rows.
- //
- // Views act like pointers to the actual collections, setting a view to a new
- // value does not alter the collection to which this view pointed previously.
- //
- // The protocol used for this class mimics the way many other collection
- // classes are defined. For example, when used with MFC, you will see member
- // definitions such as c4_View::GetSize, c4_View::GetAt, c4_View::InsertAt.
- //
- // The elements of views can be referred to by their 0-based index, which
- // produces a row-reference of type c4_RowRef. These row references can
- // be copied, used to get or set properties, or dereferenced (in which case
- // an object of class c4_Row is returned). Taking the address of a row
- // reference produces a c4_Cursor, which acts very much like a pointer.
- //
- // The following code creates a view with 1 row and 2 properties:
- //
- // c4_StringProp pName ("Name");
- // c4_IntProp pAge ("Age");
- //
- // c4_Row data;
- // pName (data) = "John Williams";
- // pAge (data) = 43;
- //
- // c4_View myView;
- // myView.Add(row);
-
- class c4_View
- {
- c4_Sequence* _seq;
-
- public:
- /* Construction / destruction / assignment */
- c4_View (c4_Sequence* implementation_ =0);
- //: Constructs a view based on a sequence.
- c4_View (const c4_Property& property_);
- //: Constructs an empty view with one property.
- c4_View (const c4_View& view_);
- //: Constructs a view from another one.
- ~c4_View ();
-
- c4_View& operator= (const c4_View& source_);
- //: Makes this view the same as another one.
-
- /* Getting / setting the number of rows */
- int GetSize() const;
- //: Returns the number of entries.
- int GetUpperBound() const;
- //: Returns highest index (size - 1).
-
- void SetSize(int newSize_, int growBy_ =-1);
- //: Changes the size of this view.
- void RemoveAll();
- //: Removes all entries (sets size to zero).
-
- /* Getting / setting individual elements */
- c4_RowRef GetAt(int index_) const;
- //: Returns a reference to specified entry.
- c4_RowRef operator[] (int index_) const;
- //: Shorthand for c4_View::GetAt.
-
- void SetAt(int index_, c4_RowRef row_);
- //: Changes the value of the specified entry.
- c4_RowRef ElementAt(int index_);
- //: Element access, for use as RHS or LHS.
-
- /* These can increase the number of rows */
- void SetAtGrow(int index_, c4_RowRef row_);
- //: Sets an entry, growing the view if needed.
- int Add(c4_RowRef row_);
- //: Adds a new entry at the end.
-
- /* Insertion / deletion of rows */
- void InsertAt(int index_, c4_RowRef row_, int count_ =1);
- //: Inserts one or more copies of an entry.
- void RemoveAt(int index_, int count_ =1);
- //: Removes entries starting at the given index.
- void InsertAt(int index_, const c4_View& view_);
- //: Inserts a copy of the contents of another view.
-
- /* Dealing with the properties of this view */
- int NumProperties() const;
- //: Returns the number of properties.
- int NthProperty(int column_) const;
- //: Returns the id of the N-th property.
- int FindProperty(int id_);
- //: Finds the index of a property, given its id.
-
- /* Structural information */
- c4_View Structure() const;
- //: Returns a view which describes the structure of this view.
- c4_String Describe() const;
- //: Returns a description of the structure.
- static c4_String Description(const c4_View& view_);
- //: Returns a homogenized description of this view.
-
- c4_View Clone() const;
- //: Constructs a new view with the same structure but no data.
- void AddProperty(const c4_Property& property_);
- //: Adds a property column to a view if not already present.
- c4_View operator, (const c4_Property& property_) const;
- //: Returns a view like the first, with a property appended to it.
-
- /* Derived views */
- c4_View Sort() const;
- //: Creates view with all rows in natural (property-wise) order.
- c4_View SortOn(const c4_View& order_) const;
- //: Creates view sorted according to the specified properties.
- c4_View SortOnReverse(const c4_View& order_, const c4_View& orderDown_) const;
- //: Creates sorted view, with some properties sorted in reverse.
-
- c4_View Select(c4_RowRef criterium_) const;
- //: Creates a view with rows matching the specified value.
- c4_View SelectRange(c4_RowRef rowLow_, c4_RowRef rowHigh_) const;
- //: Creates a view with row values within the specified range.
-
- c4_View Project(const c4_View& order_) const;
- //: Creates a view with the specified property arrangement.
- c4_View ProjectWithout(const c4_View& order_) const;
- //: Creates a derived view with some properties omitted.
-
- int GetIndexOf(c4_RowRef row_) const;
- //: Returns the index of the specified row in this view (or -1).
-
- /* Searching */
- int Find(c4_RowRef key_, int start_ =0) const;
- //: Finds index of the the next entry matching the specified key.
- int Search(c4_RowRef key_) const;
- //: Searches for a key, using the native sort order of the view.
-
- protected:
- void _IncSeqRef();
- void _DecSeqRef();
-
- friend class c4_ViewRef;
- };
-
- /////////////////////////////////////////////////////////////////////////////
- //: An iterator for collections of rows (views).
- //
- // Cursor objects can be used to point to specific entries in a view.
- // A cursor acts very much like a pointer to a row in a view, and is
- // returned when taking the address of a c4_RowRef. Dereferencing
- // a cursor leads to the original row reference again. You can construct a
- // cursor for a c4_Row, but since such rows are not part of a collection,
- // incrementing or decrementing these cursors is meaningless (and wrong).
- //
- // The usual range of pointer operations can be applied to these objects:
- // pre/post-increment and decrement, adding or subtracting integer offsets,
- // as well as the full range of comparison operators. If two cursors
- // point to entries in the same view, their difference can be calculated.
- //
- // As with regular pointers, care must be taken to avoid running off of
- // either end of a view (the debug build includes assertions to check this).
-
- class c4_Cursor
- {
- c4_Sequence* _seq;
- /* Pointer to the sequence. */
- int _index;
- /* Current index into the sequence. */
-
- public:
- /* Construction / destruction / dereferencing */
- c4_Cursor (c4_Sequence& implementation_, int index_);
- //: Constructs a new cursor.
-
- c4_RowRef operator* () const;
- //: Dereferences this cursor to "almost" a row.
-
- c4_RowRef operator[] (int index_) const;
- //: This is the same as *(cursor + offset).
-
- /* Stepping the iterator forwards / backwards */
- c4_Cursor& operator++ ();
- //: Pre-increments the cursor.
- c4_Cursor operator++ (int);
- //: Post-increments the cursor.
- c4_Cursor& operator-- ();
- //: Pre-decrements the cursor.
- c4_Cursor operator-- (int);
- //: Post-decrements the cursor.
-
- c4_Cursor& operator+= (int offset_);
- //: Advances by a given offset.
- c4_Cursor& operator-= (int offset_);
- //: Backs up by a given offset.
-
- c4_Cursor operator- (int) const;
- //: Subtracts a specified offset.
- int operator- (c4_Cursor cursor_) const;
- //: Returns the distance between two cursors.
-
- friend c4_Cursor operator+ (c4_Cursor cursor_, int offset_);
- //: Adds specified offset.
- friend c4_Cursor operator+ (int offset_, c4_Cursor cursor_);
- //: Adds specified offset to cursor.
-
- /* Comparing row positions */
- friend bool operator== (c4_Cursor a_, c4_Cursor b_);
- //: Returns true if both cursors are equal.
- friend bool operator!= (c4_Cursor a_, c4_Cursor b_);
- //: Returns true if both cursors are not equal.
- friend bool operator< (c4_Cursor a_, c4_Cursor b_);
- //: True if first cursor is less than second cursor.
- friend bool operator> (c4_Cursor a_, c4_Cursor b_);
- //: True if first cursor is greater than second cursor.
- friend bool operator<= (c4_Cursor a_, c4_Cursor b_);
- //: True if first cursor is less or equal to second cursor.
- friend bool operator>= (c4_Cursor a_, c4_Cursor b_);
- //: True if first cursor is greater or equal to second cursor.
-
- friend class c4_Reference;
- friend class c4_Row;
- friend class c4_RowRef;
- friend class c4_View;
-
- friend class c4_Sequence;
- friend class c4_FilterSeq;
- friend class c4_SortSeq;
-
- friend bool operator== (c4_RowRef a_, c4_RowRef b_);
- friend bool operator< (c4_RowRef a_, c4_RowRef b_);
- };
-
- /////////////////////////////////////////////////////////////////////////////
- //: Reference to a data row, can be used on either side of an assignment.
- //
- // Row references are created when dereferencing a c4_Cursor or when
- // indexing an element of a c4_View. Assignment will change the
- // corresponding item. Rows (objects of type c4_Row) are a special
- // case of row references, consisting of a view with exactly one item.
- //
- // Internally, row references are very similar to cursors, in fact they are
- // little more than a wrapper around them. The essential difference is one
- // of semantics: comparing row references compares contents, copying row
- // references copies the contents, whereas cursor comparison and copying
- // deals with the pointer to the row, not its contents.
-
- class c4_RowRef
- {
- c4_Cursor _cursor;
- /* A row reference is a cursor in disguise. */
-
- public:
- /* General operations */
- c4_RowRef operator= (const c4_RowRef& row_);
- //: Assigns the value of another row to this one.
- c4_Cursor operator& () const;
- //: Returns the cursor associated to this row.
- c4_View Container() const;
- //: Returns the underlying container view.
-
- /* Comparing row contents */
- friend bool operator== (c4_RowRef a_, c4_RowRef b_);
- //: Returns true if the contents of both rows are equal.
- friend bool operator!= (c4_RowRef a_, c4_RowRef b_);
- //: Returns true if the contents of both rows are not equal.
- friend bool operator< (c4_RowRef a_, c4_RowRef b_);
- //: True if first row is less than second row.
- friend bool operator> (c4_RowRef a_, c4_RowRef b_);
- //: True if first row is greater than second row.
- friend bool operator<= (c4_RowRef a_, c4_RowRef b_);
- //: True if first row is less or equal to second row.
- friend bool operator>= (c4_RowRef a_, c4_RowRef b_);
- //: True if first row is greater or equal to second row.
-
- protected:
- c4_RowRef (c4_Cursor);
-
- friend class c4_Cursor;
- friend class c4_Row;
- };
-
- /////////////////////////////////////////////////////////////////////////////
- //: An entry in a collection with copy semantics.
- //
- // Rows can exist by themselves and as the contents of views. Row assignment
- // implies that a copy of the contents of the originating row is made.
- //
- // A row is implemented as an unattached view with exactly one element.
-
- class c4_Row : public c4_RowRef
- {
- public:
- c4_Row ();
- //: Constructs a row with no properties.
- c4_Row (const c4_Row& row_);
- //: Constructs a row from another one.
- c4_Row (const c4_RowRef& row_);
- //: Constructs a row copy from a row reference.
- ~c4_Row ();
-
- c4_Row& operator= (const c4_Row& row_);
- //: Assigns a copy of another row to this one.
- c4_Row& operator= (const c4_RowRef& row_);
- //: Copies another row to this one.
-
- void ConcatRow(const c4_RowRef& row_);
- //: Adds all properties and values into this row.
- friend c4_Row operator+ (const c4_RowRef& a_, const c4_RowRef& b_);
- //: Returns a new row which is the concatenation of two others.
-
- private:
- static c4_Cursor Allocate();
- static void Release(c4_Cursor);
- };
-
- /////////////////////////////////////////////////////////////////////////////
- //: Manager for persistent storage of view structures.
- //
- // The storage class uses a view, with additional functionality to be able
- // to store and reload the data it contains (including nested subviews).
- //
- // By default, data is loaded on demand, i.e. whenever data which has
- // not yet been referenced is used for the first time. Loading is limited
- // to the lifetime of this storage object, since the storage object carries
- // the file descriptor with it that is needed to access the data file.
- //
- // To save changes, call the Commit member. This is the only time
- // that data is written to file - when using a read-only file simply avoid
- // calling Commit.
- //
- // The LoadFromStream and SaveToStream members can be used to
- // serialize the contents of this storage row using only sequential I/O
- // (no seeking, only read or write calls).
- //
- // The data storage mechanism implementation provides fail-safe operation:
- // if anything prevents Commit from completing its task, the last
- // succesfully committed version of the saved data will be recovered on
- // the next open. This also includes changes made to the table structure.
- //
- // The following code creates a view with 1 row and stores it on file:
- //
- // c4_StringProp pName ("Name");
- // c4_IntProp pAge ("Age");
- //
- // c4_Storage storage ("myfile.dat", true);
- // c4_View myView = storage.GetAs("Musicians[Name:S,Age:I]");
- //
- // myView.Add(pName ["John Williams"] + pAge [43]);
- //
- // storage.Commit();
-
- class c4_Storage
- {
- c4_Persist* _persist;
- c4_Strategy* _cleanup;
- bool (c4_Storage::*_fCommit) ();
-
- public:
- c4_Storage (c4_File* file_ =0);
- //: Constructs streaming-only or descriptor-based storage object.
- c4_Storage (c4_Strategy& strategy_);
- //: Constructs a storage using the specified strategy handler.
- c4_Storage (const char* filename_, const char* description_);
- //: Constructs a storage object for given file and format.
- c4_Storage (const char* filename_, bool canModify_);
- //: Constructs a storage object, keeping the current structure.
- ~c4_Storage ();
-
- void AutoCommit();
- //: Sets storage up to always call Commit in the destructor.
- c4_RowRef Contents() const;
- //: Gives access to the stored data as a single row.
-
- c4_Strategy& Strategy() const;
- //: Returns the strategy object associated with this storage.
- c4_Table& RootTable() const;
- //: Returns the root table entry.
- c4_String Description() const;
- //: Returns a description of the data structure.
-
- bool Commit();
- //: Flushes pending changes to file right now.
- bool Rollback();
- //: (Re)initializes for on-demand loading.
- // This will cancel all uncommitted changes.
-
- c4_ViewRef View(const char* name_) const;
- //: Used to get or set a named view in this storage object.
- c4_View GetAs(const char* description_);
- //: Get a named view, redefining it to match the given structure.
- c4_View Store(const char* name_, const c4_View& view_);
- //: Attaches a view using specified name in this storage object.
-
- void LoadFromStream(void* _auxArg);
- //: Loads contents from the specified input stream.
- void SaveToStream(void* _auxArg);
- //: Saves contents to the specified output stream.
-
- private:
- c4_Storage (const c4_Storage&); // not implemented
- void operator= (const c4_Storage&); // not implemented
-
- void Initialize(const char*, bool);
- void SetStructure(const char*);
- };
-
- /////////////////////////////////////////////////////////////////////////////
- //: Generic data buffer, with optional automatic clean up.
- //
- // These objects are used to pass around untyped data without concern about
- // clean-up. They know whether the bytes need to be de-allocated when these
- // objects go out of scope. Small amounts of data are stored in the object.
- //
- // Objects of this class are used a lot within MetaKit to manipulate its own
- // data items generically. The c4_BytesProp class allows storing binary
- // data explicitly in a file. If such data files must be portable, then the
- // application itself must define a generic format to deal with byte order.
- //
- // How to store an object in binary form in a row (this is not portable):
- //
- // struct MyStruct { ... };
- // MyStruct something;
- //
- // c4_BytesProp pData ("Data");
- // c4_Row row;
- //
- // pData (row) = c4_Bytes (&something, sizeof something);
-
- class c4_Bytes
- {
- t4_byte* _contents;
- int _size;
- bool _copy;
-
- enum { kMaxBuf = 16 };
- t4_byte _buffer [kMaxBuf];
-
- public:
- c4_Bytes ();
- //: Constructs an empty binary object.
- c4_Bytes (const void* buffer_, int length_);
- //: Constructs an object with contents, no copy.
- c4_Bytes (const void* buffer_, int length_, bool makeCopy_);
- //: Constructs an object with contents, optionally as a copy.
- c4_Bytes (const c4_Bytes& bytes_);
- //: Copy constructor.
- ~c4_Bytes ();
-
- c4_Bytes& operator= (const c4_Bytes& bytes_);
- //: Assignment, this may make a private copy of contents.
- void Swap(c4_Bytes& bytes_);
- //: Swaps the contents and ownership of two byte objects.
-
- int Size() const;
- //: Returns the number of bytes of its contents.
- const t4_byte* Contents() const;
- //: Returns a pointer to the contents.
-
- t4_byte* SetBuffer(int length_);
- //: Defines contents as a freshly allocated buffer of given size.
- t4_byte* SetBufferClear(int length_);
- //: Allocates a buffer and fills its contents with zero bytes.
-
- friend bool operator== (const c4_Bytes& a_, const c4_Bytes& b_);
- //: Returns true if the contents of both objects are equal.
- friend bool operator!= (const c4_Bytes& a_, const c4_Bytes& b_);
- //: Returns true if the contents of both objects are not equal.
-
- private:
- void _MakeCopy();
- void _LoseCopy();
- };
-
- /////////////////////////////////////////////////////////////////////////////
- //: Base class for the basic data types.
- //
- // Property objects exist independently of view, row, and storage objects.
- // They have a name and type, and can be used by multiple views.
- // You will normally only use derived classes for strong typing.
- //
- // See: c4_IntProp, c4_FloatProp, c4_DoubleProp,
- // c4_StringProp, c4_BytesProp, c4_ViewProp
-
- class c4_Property
- {
- int _id;
-
- public:
- c4_Property (char type_, const char* name_);
- //: Constructs a new property with the give type and name.
- c4_Property (int ide_);
- //: Constructs a property from its id.
- ~c4_Property ();
-
- c4_Property (const c4_Property& property_);
- //: Copy constructor.
- void operator= (const c4_Property& property_);
- //: Assignment.
-
- c4_String Name() const;
- //: Returns the name of this property.
- char Type() const;
- //: Returns the type of this property.
-
- int GetId() const;
- //: Returns a unique id for this property.
- // Properties with the same type and name always share the same id.
-
- c4_Reference operator() (c4_RowRef row_) const;
- //: Gets or sets this untyped property in a row.
-
- void Refs(int) const;
- //: Adjusts the reference count.
-
- c4_View operator, (const c4_Property& prop_) const;
- //: Returns a view like the first, with a property appended to it.
- };
-
- //: Integer properties.
- class c4_IntProp : public c4_Property
- {
- public:
- c4_IntProp (const char* name_);
- //: Constructs a new property.
-
- c4_IntRef operator() (c4_RowRef row_);
- //: Gets or sets an integer property in a row.
- t4_i32 Get(c4_RowRef row_);
- //: Gets an integer property in a row.
- void Set(c4_RowRef row_, t4_i32 value_);
- //: Sets an integer property in a row.
-
- c4_Row operator[] (t4_i32 value_);
- //: Creates a row with one integer, shorthand for AsRow.
- c4_Row AsRow(t4_i32 value_);
- //: Creates a row with one integer.
- };
-
- #if !q4_TINY
-
- //: Floating point properties.
- class c4_FloatProp : public c4_Property
- {
- public:
- c4_FloatProp (const char* name_);
- //: Constructs a new property.
-
- c4_FloatRef operator() (c4_RowRef row_);
- //: Gets or sets a floating point property in a row.
- double Get(c4_RowRef row_);
- //: Gets a floating point property in a row.
- void Set(c4_RowRef row_, double value_);
- //: Sets a floating point property in a row.
-
- c4_Row operator[] (double value_);
- //: Creates a row with one floating point value, shorthand for AsRow.
- c4_Row AsRow(double value_);
- //: Creates a row with one floating point value.
- };
-
- //: Double precision properties.
- class c4_DoubleProp : public c4_Property
- {
- public:
- c4_DoubleProp (const char* name_);
- //: Constructs a new property.
-
- c4_DoubleRef operator() (c4_RowRef row_);
- //: Gets or sets a double precision property in a row.
- double Get(c4_RowRef row_);
- //: Gets a double precision property in a row.
- void Set(c4_RowRef row_, double value_);
- //: Sets a double precision property in a row.
-
- c4_Row operator[] (double value_);
- //: Creates a row with one double precision value, shorthand for AsRow.
- c4_Row AsRow(double value_);
- //: Creates a row with one double precision value.
- };
-
- #endif // !q4_TINY
-
- //: String properties.
- class c4_StringProp : public c4_Property
- {
- public:
- c4_StringProp (const char* name_);
- //: Constructs a new property.
-
- c4_StringRef operator() (c4_RowRef row_);
- //: Gets or sets a string property in a row.
- c4_String Get(c4_RowRef row_);
- //: Gets a string property in a row.
- void Set(c4_RowRef row_, const char* value_);
- //: Sets a string property in a row.
-
- c4_Row operator[] (const char* value_);
- //: Creates a row with one string, shorthand for AsRow.
- c4_Row AsRow(const char* value_);
- //: Creates a row with one string.
- };
-
- //: Binary properties.
- class c4_BytesProp : public c4_Property
- {
- public:
- c4_BytesProp (const char* name_);
- //: Constructs a new property.
-
- c4_BytesRef operator() (c4_RowRef row_);
- //: Gets or sets a bytes property in a row.
- c4_Bytes Get(c4_RowRef row_);
- //: Gets a bytes property in a row.
- void Set(c4_RowRef row_, const c4_Bytes& value_);
- //: Sets a bytes property in a row.
-
- c4_Row operator[] (const c4_Bytes& value_);
- //: Create a row with one bytes object, shorthand for AsRow.
- c4_Row AsRow(const c4_Bytes& value_);
- //: Create a row with one bytes object.
- };
-
- //: View properties.
- class c4_ViewProp : public c4_Property
- {
- public:
- c4_ViewProp (const char* name_);
- //: Constructs a new property.
-
- c4_ViewRef operator() (c4_RowRef row_);
- //: Gets or sets a view property in a row.
- c4_View Get(c4_RowRef row_);
- //: Gets a view property in a row.
- void Set(c4_RowRef row_, const c4_View& value_);
- //: Sets a view property in a row.
-
- c4_Row operator[] (const c4_View& value_);
- //: Create a row with one view, shorthand for AsRow.
- c4_Row AsRow(const c4_View& value_);
- //: Create a row with one view.
- };
-
- /////////////////////////////////////////////////////////////////////////////
-
- #include "k4viewx.h"
-
- #if q4_INLINE
- #include "k4view.inl"
- #endif
-
- /////////////////////////////////////////////////////////////////////////////
-
- #endif
-